# -*- coding: utf-8 -*-
# @ Time   :  2022/6/9 
# @ Author : dengjianping
# @ File :  async_tool
# @ Desc : flask 异步协程装饰器
import asyncio
from functools import wraps
from typing import Callable

from concurrent.futures import (
                                Future, 
                                ThreadPoolExecutor
                                )                                
from flask import  (
    has_request_context, 
    copy_current_request_context
    )

'''
app = Flask(__name__)


@app.route('/async')
@run_async
async def index():
    await asyncio.sleep(0.2)
    return jsonify('hello')


@app.route('/sync')
def aindex():
    sleep(0.2)
    return jsonify('hello')


import logging

# logging.getLogger('werkzeug').setLevel(logging.ERROR)
app.run(port=8000)
'''
def run_async(func):
    @wraps(func)
    def _wrapper(*args, **kwargs) -> Callable:
        call_result = Future()

        def _run():
            loop = asyncio.new_event_loop()
            try:
                result = loop.run_until_complete(func(*args, **kwargs))
            except Exception as error:
                call_result.set_exception(error)
            else:
                call_result.set_result(result)
            finally:
                loop.close()

        loop_executor = ThreadPoolExecutor(max_workers=10)
        if has_request_context():
            _run = copy_current_request_context(_run)
        loop_future = loop_executor.submit(_run)
        loop_future.result()
        return call_result.result()

    return _wrapper




